﻿#include "gb_table_search.hpp"

#include <cstddef>
#include <iostream>
#include <iomanip>

#include "gb_table/gb_table_symbol.ipp"
#include "gb_table/gb_table1_2byte_21003.ipp"
#include "gb_table/gb_table2_4byte_extend_A_6530.ipp"

#if !defined(DISABLE_GB18030_2005_CONV)
	#include "gb_table/gb_table3_4byte_extend_B_42711.ipp"
#endif


namespace detail {
#if 0
template <typename T>
T bsearch_t(const T* arr,
			size_t arr_size,
			const T& key,
			bool search_first)
{
	size_t low = search_first ? 0 : 1;
	size_t high = arr_size - 1 - (search_first ? 1 : 0);
	size_t mid = 0;
	size_t mod = 0;

	while (low <= high)
	{
		mid = (low + high) / 2;
		mod = mid % 2;

		if ((mod == 1 && search_first) ||
				(mod == 0 && !search_first))
			mid -= 1;

		std::cout << "mid is " << mid << " low is = " << low << " high is " << high <<
				  " value is " << arr[mid] << std::endl;

		if (arr[mid] < key)
			low = mid + 2;
		else if (arr[mid] > key && mid >= 2)
			high = mid - 2;
		else
			return arr[search_first ? mid + 1 : mid - 1];
	}

	return 0;
}
#endif

// 双向查找，无法排序，只能遍历
template <typename T>
T unordered_search(const T* arr,
				   size_t arr_size,
				   const T& key,
				   bool  search_first)
{
	size_t i = search_first ? 0 : 1;

	for (; i < arr_size ; i += 2)
		if (arr[i] == key)
			return arr[search_first ? i + 1 : i - 1];

	return 0;
}
}

static const
size_t kTableSymbolSize = sizeof(gb_table_symbol) / sizeof(uint16_t);

//
static const
size_t kTable1Size = sizeof(gb_table1_2byte_21003) / sizeof(uint16_t);

///
static const
size_t kTable2Size = sizeof(gb_table2_4byte_extend_A_6530) / sizeof(uint32_t);

///
static const
size_t kTable3Size = sizeof(gb_table3_4byte_extend_B_42711) / sizeof(uint32_t);


uint16_t _search_gb2_symbol_by_u16(uint16_t code)
{
	return detail::unordered_search(gb_table_symbol, kTableSymbolSize, code, false);
}

uint16_t _search_u16_symbol_by_gb2(uint16_t code)
{
	return detail::unordered_search(gb_table_symbol, kTableSymbolSize, code, true);
}

uint16_t _search_gbk_by_u16(uint16_t code)
{
	return detail::unordered_search(gb_table1_2byte_21003, kTable1Size, code, false);
}

uint16_t _search_u16_by_gbk(uint16_t code)
{
	return detail::unordered_search(gb_table1_2byte_21003, kTable1Size, code, true);
}

uint32_t _search_gb4A_by_u16(uint16_t code)
{
	return detail::unordered_search(gb_table2_4byte_extend_A_6530, kTable2Size, uint32_t(code), false);
}

uint16_t _search_u16_by_gb4A(uint32_t code)
{
	return detail::unordered_search(gb_table2_4byte_extend_A_6530, kTable2Size, uint32_t(code), true);
}

#if !defined(DISABLE_GB18030_2005_CONV)

uint32_t _search_gb4B_by_u32(uint32_t code)
{
	return detail::unordered_search(gb_table3_4byte_extend_B_42711, kTable3Size, uint32_t(code), false);
}

uint32_t _search_u32_by_gb4B(uint32_t code)
{
	return detail::unordered_search(gb_table3_4byte_extend_B_42711, kTable3Size, code, true);
}

#endif